package com.sheng.leetcode.year2022.swordfingeroffer.day26;

import org.junit.Test;

/**
 * @author liusheng
 * @date 2022/09/26
 *<p>
 * 剑指 Offer 20. 表示数值的字符串<p>
 *<p>
 * 请实现一个函数用来判断字符串是否表示数值（包括整数和小数）。<p>
 * 数值（按顺序）可以分成以下几个部分：<p>
 *<p>
 * 若干空格<p>
 * 一个小数或者整数<p>
 * （可选）一个'e'或'E'，后面跟着一个整数<p>
 * 若干空格<p>
 *<p>
 * 小数（按顺序）可以分成以下几个部分：<p>
 *<p>
 * （可选）一个符号字符（'+' 或 '-'）<p>
 * 下述格式之一：<p>
 * 至少一位数字，后面跟着一个点 '.'<p>
 * 至少一位数字，后面跟着一个点 '.' ，后面再跟着至少一位数字<p>
 * 一个点 '.' ，后面跟着至少一位数字<p>
 * 整数（按顺序）可以分成以下几个部分：<p>
 *<p>
 * （可选）一个符号字符（'+' 或 '-'）<p>
 * 至少一位数字<p>
 *<p>
 * 部分数值列举如下：<p>
 * ["+100", "5e2", "-123", "3.1416", "-1E-16", "0123"]<p>
 * 部分非数值列举如下：<p>
 * ["12e", "1a3.14", "1.2.3", "+-5", "12e+5.4"]<p>
 *<p>
 * 示例 1：<p>
 * 输入：s = "0"<p>
 * 输出：true<p>
 *<p>
 * 示例 2：<p>
 * 输入：s = "e"<p>
 * 输出：false<p>
 *<p>
 * 示例 3：<p>
 * 输入：s = "."<p>
 * 输出：false<p>
 *<p>
 * 示例 4：<p>
 * 输入：s = "    .1  "<p>
 * 输出：true<p>
 *<p>
 * 提示：<p>
 *<p>
 * 1 <= s.length <= 20<p>
 * s 仅含英文字母（大写和小写），数字（0-9），加号 '+' ，减号 '-' ，空格 ' ' 或者点 '.' 。<p>
 *<p>
 * 来源：力扣（LeetCode）<p>
 * 链接：<a href="https://leetcode.cn/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof">...</a><p>
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。<p>
 */
public class Sword0020 {

    @Test
    public void test01() {
        // true，false，false，true
        String s = "0";
//        String s = "e";
//        String s = ".";
//        String s = "    .1  ";
        System.out.println(new Solution().isNumber(s));
    }
}
class Solution {
    public boolean isNumber(String s) {
        char[] str = s.toCharArray();
        // 字符串空白，直接返回false
        if (str.length <= 0) {
            return false;
        }
        int[] index = {0};
        boolean numeric = scanInteger(str,index);
        // 判断小数部分
        if (index[0] < str.length && str[index[0]] == '.') {
            index[0]++;
            // 之所以使用||，而没有使用&&的原因。小数可以没有整数部分，如.123等于0.123；小数点后面可以没有数字，如233.等于233.0；当然，小数点前后都可以有数字，如1.123；
            // (true||false)代表小数点前面没有整数，（true||true）代表小数点前面有整数，（false||true）代表小数点后面没有整数
            numeric = scanUnsignedInteger(str,index) || numeric;
        }
        // 判断指数部分
        if (index[0] < str.length && (str[index[0]] == 'e' || str[index[0]] == 'E')) {
            index[0]++;
            if (index[0] == str.length) {
                return false;
            }
            numeric = numeric && scanInteger(str,index);
        }
        return numeric && index[0] == str.length;
    }

    /**
     * 判断是否是整数
     *
     * @param str
     * @param index
     * @return
     */
    public boolean scanInteger(char[] str,int[] index){
        if (index[0] < str.length && (str[index[0]] == '+' || str[index[0]] == '-')) {
            index[0]++;
        }
        return scanUnsignedInteger(str,index);
    }

    /**
     * 判断是否是无符号整数
     *
     * @param str
     * @param index
     * @return
     */
    public boolean scanUnsignedInteger(char[] str,int[] index){
        int temp = index[0];
        while (index[0] < str.length && (str[index[0]] >='0' && str[index[0]] <= '9')) {
            index[0]++;
        }
        return (index[0]) > temp;
    }
}
